#include "InterOpUtils.h"

#include <locale>
#include <string>
#include <codecvt>

#include "common/logger.h"
#include "pmi/InterOpDimension.h"
#include "spa_unlock_result.hxx"
#include "transf.hxx"
#include "vector.hxx"

AMCAX_EXCHANGE_NAMESPACE_BEGIN

namespace InterOp
{

    SPAIopWString StringToSPAIopWString(const std::string &std_string)
    {
        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
        std::wstring temp_str = converter.from_bytes(std_string);
        SPAIopWString spa_string(temp_str.c_str());
        return spa_string;
    }


    std::string SPAIopWStringToString(const SPAIopWString &spaString)
    {
        const wchar_t *tempStr{nullptr};
        spaString.ToWChar(tempStr);
        if (tempStr == nullptr)
            return "TransferFailed";

        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;

        return converter.to_bytes(tempStr);
    }

    bool CheckLicense(const std::string &spaLicence, SPAIopAcisSystemInitGuard *initGuard)
    {
        int result = 0;
        static std::mutex mtx;
        try
        {
            if (nullptr == initGuard)
            {
                std::lock_guard<std::mutex> lock(mtx);
                initGuard = new SPAIopAcisSystemInitGuard(spaLicence.c_str());
            }
            result = initGuard->GetInitStatus();
        }
        catch (SPAIopAcisError &error)
        {
            ShowAcisErrorMsg(error);
        }
        catch (...)
        {
            LOG_ERROR("FAILURE: Unknown exception caught!");
        }

        if (SPA_UNLOCK_NO_MSG == result)
        {
            LOG_INFO("Initialize success. start conversion....");
            return true;
        }
        else if (SPA_UNLOCK_KEY_WARN_EXPIRE == result)
        {
            LOG_WARN("lisence key will expire soon.");
            return true;
        }
        else if (SPA_UNLOCK_REGISTRATION_WARN_EXPIRE == result)
        {
            LOG_WARN("registration will expire soon.");
            return true;
        }
        else
        {
            LOG_ERROR("unexpected value, Contact supporter.");
            return false;
        }
        return false;
    }

    void ShowAcisErrorMsg(const SPAIopAcisError &error)
    {
        SPAIopWString req = error.GetRequest();
        SPAIopWString diagnostic = error.GetDiagnostic();
        SPAIopWString advice = error.GetAdvice();
        LOG_ERROR("Error Msg, req:{}, diagnostic:{}, advice:{}",
                  SPAIopWStringToString(req), SPAIopWStringToString(diagnostic), SPAIopWStringToString(advice));
    }

    SPAtransf GenerateTransform(const double oAffineTransform[3][3], const double oTranslation[3])
    {
        
        SPAvector row1(oAffineTransform[0][0], oAffineTransform[0][1], oAffineTransform[0][2]);
        SPAvector row2(oAffineTransform[1][0], oAffineTransform[1][1], oAffineTransform[1][2]);
        SPAvector row3(oAffineTransform[2][0], oAffineTransform[2][1], oAffineTransform[2][2]);
        SPAmatrix matrix(row1, row2, row3);
        SPAvector translation(oTranslation[0], oTranslation[1], oTranslation[2]);
        SPAtransf transf = make_transf(matrix, translation);
        return transf;
    }

    namespace  PMI::Helper {

        PMIFont ToFont(const SPAIopPMIFont &iFont) {
            PMIFont font = PMIFont::Simplex;
            switch (iFont)
            {
            case SPAIopPMI_Simplex:
                font = PMIFont::Simplex;
                break;
            case SPAIopPMI_Din:
                font = PMIFont::Din;
                break;
            case SPAIopPMI_Military:
                font = PMIFont::Military;
                break;
            case SPAIopPMI_ISO:
                font = PMIFont::ISO;
                break;
            case SPAIopPMI_Lightline:
                font = PMIFont::Lightline;
                break;
            case SPAIopPMI_Century:
                font = PMIFont::Century;
                break;
            case SPAIopPMI_IGES_1001:
                font = PMIFont::IGES_1001;
                break;
            case SPAIopPMI_IGES_1002:
                font = PMIFont::IGES_1002;
                break;
            case SPAIopPMI_IGES_1003:
                font = PMIFont::IGES_1003;
                break;
            default:
                LOG_ERROR("Unknown Font Type.");
                break;
            }
            return font;
        }

        PMIRoughnessObtentionType ToRoughnessObtentionType(const SPAIopPMIRoughnessObtentionType &iRoughnessObtention) {
            PMIRoughnessObtentionType obtentionType = PMIRoughnessObtentionType::UnSupported;
            switch (iRoughnessObtention)
            {
            case SPAIopPMI_RO_UnSupported:
                obtentionType = PMIRoughnessObtentionType::UnSupported;
                break;
            case SPAIopPMI_RO_NotDefined:
                obtentionType = PMIRoughnessObtentionType::NotDefined;
                break;
            case SPAIopPMI_RO_MachiningMandatory:
                obtentionType = PMIRoughnessObtentionType::MachiningMandatory;
                break;
            case SPAIopPMI_RO_MachiningForbidden:
                obtentionType = PMIRoughnessObtentionType::MachiningForbidden;
                break;
            default:
                LOG_ERROR("Unknown Roughness Obtention Type.");
                break;
            }
            return obtentionType;
        }


        PMIRoughnessApplicabilityType ToRoughnessApplicabilityType(const SPAIopPMIRoughnessApplicabilityType &iRoughnessApplicability) 
        {
            PMIRoughnessApplicabilityType applicabilityType = PMIRoughnessApplicabilityType::UnSupported;
            switch (iRoughnessApplicability)
            {
            case SPAIopPMI_RA_UnSupported:
                applicabilityType = PMIRoughnessApplicabilityType::UnSupported;
                break;
            case SPAIopPMI_RA_SpecifiedSurfaceOnly:
                applicabilityType = PMIRoughnessApplicabilityType::SpecifiedSurfaceOnly;
                break;
            case SPAIopPMI_RA_AllPartSurfaces:
                applicabilityType = PMIRoughnessApplicabilityType::AllPartSurfaces;
                break;  
            case SPAIopPMI_RA_BasicSurface:
                applicabilityType = PMIRoughnessApplicabilityType::BasicSurface;
                break;
            default:    
                LOG_ERROR("Unknown Roughness Applicability Type.");
                break;
            }   
            return applicabilityType;
        }

        PMIDatumTargetType ToDatumTargetType(const SPAIopPMIDatumTargetType &iDatumTargetType) 
        {
            PMIDatumTargetType datumTargetType = PMIDatumTargetType::Unknown;
            switch (iDatumTargetType)
            {
            case SPAIopPMI_DTT_Unknown:
                datumTargetType = PMIDatumTargetType::Unknown;
                break;
            case SPAIopPMI_DTT_Point:
                datumTargetType = PMIDatumTargetType::Point;
                break;
            case SPAIopPMI_DTT_Line:
                datumTargetType = PMIDatumTargetType::Line;
                break;
            case SPAIopPMI_DTT_AreaCircular:
                datumTargetType = PMIDatumTargetType::AreaCircular;
                break;
            case SPAIopPMI_DTT_AreaRectangular:
                datumTargetType = PMIDatumTargetType::AreaRectangular;
                break;
            case SPAIopPMI_DTT_AreaFace:
                datumTargetType = PMIDatumTargetType::AreaFace;
                break;
            case SPAIopPMI_DTT_Feature:
                datumTargetType = PMIDatumTargetType::Feature;
                break;  
            case SPAIopPMI_DTT_UserDefined:
                datumTargetType = PMIDatumTargetType::UserDefined;
                break;  
            default:    
                LOG_ERROR("Unknown Datum Target Type.");
                break;
            }   
            return datumTargetType;
        }

        PMIToleranceType ToToleranceType(const SPAIopPMIToleranceType &iToleranceType) 
        {
            PMIToleranceType toleranceType = PMIToleranceType::UNKNOWN;
            switch (iToleranceType)
            {   
                case SPAIopPMI_Form_Straightness:
                    toleranceType = PMIToleranceType::Form_Straightness;
                    break;
                case SPAIopPMI_Form_Flatness:
                    toleranceType = PMIToleranceType::Form_Flatness;
                    break;
                case SPAIopPMI_Form_Circularity:
                    toleranceType = PMIToleranceType::Form_Circularity;
                    break;
                case SPAIopPMI_Form_Cylindricity:
                    toleranceType = PMIToleranceType::Form_Cylindricity;
                    break;
                case SPAIopPMI_Form_ProfileAnyLine:
                    toleranceType = PMIToleranceType::Form_ProfileAnyLine;
                    break;
                case SPAIopPMI_Form_ProfileAnySurface:
                    toleranceType = PMIToleranceType::Form_ProfileAnySurface;
                    break;
                case SPAIopPMI_Orientation_Parallelism:
                    toleranceType = PMIToleranceType::Orientation_Parallelism;
                    break;
                case SPAIopPMI_Orientation_Perpendicularity:
                    toleranceType = PMIToleranceType::Orientation_Perpendicularity;
                    break;
                case SPAIopPMI_Orientation_Angularity:
                    toleranceType = PMIToleranceType::Orientation_Angularity;
                    break;
                case SPAIopPMI_Location_TruePosition:
                    toleranceType = PMIToleranceType::Location_TruePosition;
                    break;
                case SPAIopPMI_Location_Concentricity:
                    toleranceType = PMIToleranceType::Location_Concentricity;
                    break;
                case SPAIopPMI_Location_Coaxiality:
                    toleranceType = PMIToleranceType::Location_Coaxiality;
                    break;
                case SPAIopPMI_Location_Symmetry:
                    toleranceType = PMIToleranceType::Location_Symmetry;
                    break;
                case SPAIopPMI_Location_PositionOfAnyLine:
                    toleranceType = PMIToleranceType::Location_PositionOfAnyLine;
                    break;
                case SPAIopPMI_Location_PositionOfASurface: 
                    toleranceType = PMIToleranceType::Location_PositionOfASurface;
                    break;
                case SPAIopPMI_RunOut_Circular:
                    toleranceType = PMIToleranceType::RunOut_Circular;
                    break;
                case SPAIopPMI_RunOut_Total:
                    toleranceType = PMIToleranceType::RunOut_Total;
                    break;
                default:
                    LOG_ERROR("Unknown Tolerance Type.");
                    break;
            }
            return toleranceType;
        }

        PMIToleranceValueType ToToleranceValueType(const SPAIopPMIToleranceValueType &iToleranceValueType) 
        {
            PMIToleranceValueType toleranceValueType = PMIToleranceValueType::NONE;
            switch (iToleranceValueType) {
                case SPAIopPMI_ValueType_None:
                    toleranceValueType = PMIToleranceValueType::NONE;
                    break;
                case SPAIopPMI_ValueType_Diameter:
                    toleranceValueType = PMIToleranceValueType::DIAMETER;
                    break;
                case SPAIopPMI_ValueType_Radius:
                    toleranceValueType = PMIToleranceValueType::RADIUS;
                    break;
                case SPAIopPMI_ValueType_Spherical:
                    toleranceValueType = PMIToleranceValueType::SPHERICAL;
                    break;
                case SPAIopPMI_ValueType_Square:
                    toleranceValueType = PMIToleranceValueType::SQUARE;
                    break;
                default:
                    LOG_ERROR("Unknown Tolerance Value Type.");
                    break;
            }
            return toleranceValueType;
        }

        PMIToleranceModifierType ToToleranceModifierType(const SPAIopPMIToleranceModifier &iToleranceModifierType) 
        {
            PMIToleranceModifierType toleranceModifierType = PMIToleranceModifierType::NoModifier;
            switch (iToleranceModifierType) {
                case SPAIopPMI_NoModifier:
                    toleranceModifierType = PMIToleranceModifierType::NoModifier;
                    break;
                case SPAIopPMI_MaterialCondition_Unsupported:
                    toleranceModifierType = PMIToleranceModifierType::MaterialCondition_Unsupported;
                    break;
                case SPAIopPMI_MaterialCondition_Maximum:
                    toleranceModifierType = PMIToleranceModifierType::MaterialCondition_Maximum;
                    break;
                case SPAIopPMI_MaterialCondition_Least:
                    toleranceModifierType = PMIToleranceModifierType::MaterialCondition_Least;
                    break;
                case SPAIopPMI_MaterialCondition_RegardlessOfFeatureSize:
                    toleranceModifierType = PMIToleranceModifierType::MaterialCondition_RegardlessOfFeatureSize;
                    break;
                case SPAIopPMI_TangentPlane_Unsupported:
                    toleranceModifierType = PMIToleranceModifierType::TangentPlane_Unsupported;
                    break;
                case SPAIopPMI_TangentPlane_NotTangent:
                    toleranceModifierType = PMIToleranceModifierType::TangentPlane_NotTangent;
                    break;
                case SPAIopPMI_TangentPlane_Tangent:
                    toleranceModifierType = PMIToleranceModifierType::TangentPlane_Tangent;
                    break;
                case SPAIopPMI_FreeState_Unsupported:
                    toleranceModifierType = PMIToleranceModifierType::FreeState_Unsupported;
                    break;
                case SPAIopPMI_FreeState_Free:
                    toleranceModifierType = PMIToleranceModifierType::FreeState_Free;
                    break;
                case SPAIopPMI_FreeState_NotFree:
                    toleranceModifierType = PMIToleranceModifierType::FreeState_NotFree;
                    break;
                case SPAIopPMI_Statistical_Symbol:
                    toleranceModifierType = PMIToleranceModifierType::Statistical_Symbol;
                    break;
                case SPAIopPMI_CommonZone:
                    toleranceModifierType = PMIToleranceModifierType::CommonZone;
                    break;
                case SPAIopPMI_UnequallyDisposedZone:
                    toleranceModifierType = PMIToleranceModifierType::UnequallyDisposedZone;
                    break;
                case SPAIopPMI_ProjectedState_Projected:
                    toleranceModifierType = PMIToleranceModifierType::ProjectedState_Projected;
                    break;
                case SPAIopPMI_ProjectedState_NotProjected:
                    toleranceModifierType = PMIToleranceModifierType::ProjectedState_NotProjected;
                    break;
                case SPAIopPMI_CircleU:
                    toleranceModifierType = PMIToleranceModifierType::CircleU;
                    break;
                case SPAIopPMI_Maximum:
                    toleranceModifierType = PMIToleranceModifierType::Maximum;
                    break;
                case SPAIopPMI_MinimaxFeature:
                    toleranceModifierType = PMIToleranceModifierType::MinimaxFeature;
                    break;
                case SPAIopPMI_DerivedFeature:
                    toleranceModifierType = PMIToleranceModifierType::DerivedFeature;
                    break;
                case SPAIopPMI_DynamicProfile:
                    toleranceModifierType = PMIToleranceModifierType::DynamicProfile;
                    break;
                case SPAIopPMI_LeastSquareFeature:
                    toleranceModifierType = PMIToleranceModifierType::LeastSquareFeature;
                    break;
                case SPAIopPMI_MaximumInscribedFeature: 
                    toleranceModifierType = PMIToleranceModifierType::MaximumInscribedFeature;
                    break;
                case SPAIopPMI_MinimumCircumscribedFeature: 
                    toleranceModifierType = PMIToleranceModifierType::MinimumCircumscribedFeature;
                    break;
                case SPAIopPMI_SeparateZone:    
                    toleranceModifierType = PMIToleranceModifierType::SeparateZone;
                    break;
                case SPAIopPMI_OffsetZone:
                    toleranceModifierType = PMIToleranceModifierType::OffsetZone;
                    break;
                case SPAIopPMI_VariableAngle:
                    toleranceModifierType = PMIToleranceModifierType::VariableAngle;
                    break;
                case SPAIopPMI_OrientationConstraint:
                    toleranceModifierType = PMIToleranceModifierType::OrientationConstraint;
                    break;
                case SPAIopPMI_MinimaxAssociation:
                    toleranceModifierType = PMIToleranceModifierType::MinimaxAssociation;
                    break;
                case SPAIopPMI_MinimaxAssociationWithExternalConstraint:
                    toleranceModifierType = PMIToleranceModifierType::MinimaxAssociationWithExternalConstraint;
                    break;
                case SPAIopPMI_MinimaxAssociationWithInternalConstraint:
                    toleranceModifierType = PMIToleranceModifierType::MinimaxAssociationWithInternalConstraint;
                    break;
                case SPAIopPMI_LeastSquareAssociation:
                    toleranceModifierType = PMIToleranceModifierType::LeastSquareAssociation;
                    break;
                case SPAIopPMI_LeastSquareAssociationWithExternalConstraint:
                    toleranceModifierType = PMIToleranceModifierType::LeastSquareAssociationWithExternalConstraint;
                    break;
                case SPAIopPMI_LeastSquareAssociationWithInternalConstraint:
                    toleranceModifierType = PMIToleranceModifierType::LeastSquareAssociationWithInternalConstraint;
                    break;
                case SPAIopPMI_MinimumCircumscribedAssociation:
                    toleranceModifierType = PMIToleranceModifierType::MinimumCircumscribedAssociation;
                    break;
                case SPAIopPMI_MaximumInscribedAssociation:
                    toleranceModifierType = PMIToleranceModifierType::MaximumInscribedAssociation;
                    break;
                case SPAIopPMI_TotalRangeOfDeviations:
                    toleranceModifierType = PMIToleranceModifierType::TotalRangeOfDeviations;
                    break;
                case SPAIopPMI_PeakHeight:
                    toleranceModifierType = PMIToleranceModifierType::PeakHeight;
                    break;
                case SPAIopPMI_ValleyDepth:
                    toleranceModifierType = PMIToleranceModifierType::ValleyDepth;
                    break;
                case SPAIopPMI_StandardDeviation:
                    toleranceModifierType = PMIToleranceModifierType::StandardDeviation;
                    break;
                default:
                    LOG_ERROR("Unknown Tolerance Modifier Type.");
                    break;
            }
            return toleranceModifierType;
        }

        PMIDimensionMainType ToDimensionMainType(const SPAIopPMIDimensionMainType & mainType){
            PMIDimensionMainType result = PMIDimensionMainType::DMT_Unknown;
            switch (mainType) {
                case SPAIopPMI_DMT_Unknown:
                    result = PMIDimensionMainType::DMT_Unknown;
                    break ;
                case SPAIopPMI_DMT_Basic:
                    result = PMIDimensionMainType::DMT_Basic;
                    break ;
                case SPAIopPMI_DMT_Reference:
                    result = PMIDimensionMainType::DMT_Reference;
                    break ;
                case SPAIopPMI_DMT_Tolerance:
                    result = PMIDimensionMainType::DMT_Tolerance;
                    break ;
                case SPAIopPMI_DMT_CoordDim:
                    result = PMIDimensionMainType::DMT_CoordDim;
                    break ;
                case SPAIopPMI_DMT_HoleCallout:
                    result = PMIDimensionMainType::DMT_HoleCallout;
                    break;
                default:
                    break;
            }
            return result ;
        }

        PMIDimensionSubType ToDimensionSubType(const SPAIopPMIDimensionSubType & subType) 
        {
            PMIDimensionSubType result = PMIDimensionSubType::UNKNOWN ;
            switch (subType) {
                case SPAIopPMI_Distance:
                    result = PMIDimensionSubType::Distance ;
                    break ;
                case SPAIopPMI_DistanceOffset:
                    result = PMIDimensionSubType::DistanceOffset ;
                    break ;
                case SPAIopPMI_Length:
                    result = PMIDimensionSubType::Length ;
                    break ;
                case SPAIopPMI_Length_OR_Distance:
                    result = PMIDimensionSubType::Length_OR_Distance ;
                    break ;
                case SPAIopPMI_LengthCurvilinear:
                    result = PMIDimensionSubType::LengthCurvilinear ;
                    break ;
                case SPAIopPMI_Angle:
                    result = PMIDimensionSubType::Angle ;
                    break ;
                case SPAIopPMI_Radius:
                    result = PMIDimensionSubType::Radius ;
                    break ;
                case SPAIopPMI_RadiusTangent:
                    result = PMIDimensionSubType::RadiusTangent ;
                    break ;
                case SPAIopPMI_RadiusCylinder:
                    result = PMIDimensionSubType::RadiusCylinder ;
                    break ;
                case SPAIopPMI_RadiusEdge:
                    result = PMIDimensionSubType::RadiusEdge ;
                    break ;
                case SPAIopPMI_Diameter:
                    result = PMIDimensionSubType::Diameter ;
                    break ;
                case SPAIopPMI_DiameterTangent:
                    result = PMIDimensionSubType::DiameterTangent ;
                    break ;
                case SPAIopPMI_DiameterCylinder:
                    result = PMIDimensionSubType::DiameterCylinder ;
                    break ;
                case SPAIopPMI_DiameterEdge:
                    result = PMIDimensionSubType::DiameterEdge ;
                    break ;
                case SPAIopPMI_DiameterCone:
                    result = PMIDimensionSubType::DiameterCone ;
                    break ;
                case SPAIopPMI_Chamfer:
                    result = PMIDimensionSubType::Chamfer ;
                    break ;
                case SPAIopPMI_Slope:
                    result = PMIDimensionSubType::Slope ;
                    break ;
                case SPAIopPMI_DimGDT:
                    result = PMIDimensionSubType::DimGDT ;
                    break ;
                case SPAIopPMI_DimDatumFeature:
                    result = PMIDimensionSubType::DimDatumFeature ;
                    break ;
                case SPAIopPMI_DimDatumTarget:
                    result = PMIDimensionSubType::DimDatumTarget ;
                    break ;
                case SPAIopPMI_DimBalloon:
                    result = PMIDimensionSubType::DimBalloon ;
                    break ;
                case SPAIopPMI_No_Dim:
                    result = PMIDimensionSubType::No_Dim ;
                    break ;
                case SPAIopPMI_AngleArc:
                    result = PMIDimensionSubType::AngleArc ;
                    break ;
                case SPAIopPMI_LengthCircular:
                    result = PMIDimensionSubType::LengthCircular ;
                    break ;
                case SPAIopPMI_Fillet:
                    result = PMIDimensionSubType::Fillet ;
                    break ;
                case SPAIopPMI_CoordDimension_2D:
                    result = PMIDimensionSubType::CoordDimension_2D ;
                    break ;
                case SPAIopPMI_CoordDimension_3D:
                    result = PMIDimensionSubType::CoordDimension_3D ;
                    break;
                default:
                    break;
            }
            return result ;
        }

        PMIUnit ToUnit(const SPAIopPMIUnit &featureAnnotationType) 
        {
            PMIUnit result = PMIUnit::DimUnitNone ;
            switch (featureAnnotationType) {
                case SPAIopPMI_DimUnitNone:
                    result = PMIUnit::DimUnitNone ;
                    break ;
                case SPAIopPMI_DimUnitMM:
                    result = PMIUnit::DimUnitMM ;
                    break ;
                case SPAIopPMI_DimUnitINCH:
                    result = PMIUnit::DimUnitINCH ;
                    break ;
                case SPAIopPMI_DimUnitMETER:
                    result = PMIUnit::DimUnitMETER ;
                    break ;
                case SPAIopPMI_DimUnitCM:
                    result = PMIUnit::DimUnitCM ;
                    break ;
                case SPAIopPMI_DimUnitKM:
                    result = PMIUnit::DimUnitKM ;
                    break ;
                case SPAIopPMI_DimUnitFOOT:
                    result = PMIUnit::DimUnitFOOT ;
                    break ;
                case SPAIopPMI_DimUnitF_I_F64:
                    result = PMIUnit::DimUnitF_I_F64 ;
                    break ;
                case SPAIopPMI_DimUnitF_I_F16:
                    result = PMIUnit::DimUnitF_I_F16 ;
                    break ;
                case SPAIopPMI_DimUnitF_I_DEC:
                    result = PMIUnit::DimUnitF_I_DEC ;
                    break ;
                case SPAIopPMI_DimUnitDEGREE:
                    result = PMIUnit::DimUnitDEGREE ;
                    break ;
                case SPAIopPMI_DimUnitMINUTE:
                    result = PMIUnit::DimUnitMINUTE ;
                    break ;
                case SPAIopPMI_DimUnitSECOND:
                    result = PMIUnit::DimUnitSECOND ;
                    break ;
                case SPAIopPMI_DimUnitRADIAN:
                    result = PMIUnit::DimUnitRADIAN ;
                    break ;
                case SPAIopPMI_DimUnitGRADE	:
                    result = PMIUnit::DimUnitGRADE ;
                    break ;
                default:
                    break;
            }
            return result ;
        }

        PMIDimensionFakeType ToDimensionFakeType(const SPAIopPMIDimensionFakeType & fakeType) 
        {
            PMIDimensionFakeType result = PMIDimensionFakeType::FakeUnknown ;
            switch (fakeType) {
                case SPAIopPMI_FakeUnknown:
                    result = PMIDimensionFakeType::FakeUnknown ;
                    break ;
                case SPAIopPMI_FakeNumeric:
                    result = PMIDimensionFakeType::FakeNumeric ;
                    break ;
                case SPAIopPMI_FakeText:
                    result = PMIDimensionFakeType::FakeText ;
                    break ;
                default:
                    break;
            }
            return result ;
        }

        PMIArrowSymbol ToArrowSymbol(const SPAIopPMIArrowSymbol & symbol) 
        {
            PMIArrowSymbol result = PMIArrowSymbol::NOTUSED ;
            switch (symbol) {
                case SPAIopPMI_NOTUSED:
                    result = PMIArrowSymbol::NOTUSED ;
                    break ;
                case SPAIopPMI_CROSS:
                    result = PMIArrowSymbol::CROSS ;
                    break ;
                case SPAIopPMI_PLUS:
                    result = PMIArrowSymbol::PLUS ;
                    break ;
                case SPAIopPMI_CONCENTRIC:
                    result = PMIArrowSymbol::CONCENTRIC ;
                    break ;
                case SPAIopPMI_COINCIDENT:
                    result = PMIArrowSymbol::COINCIDENT ;
                    break ;
                case SPAIopPMI_FULLCIRCLE:
                    result = PMIArrowSymbol::FULLCIRCLE ;
                    break ;
                case SPAIopPMI_FULLSQUARE:
                    result = PMIArrowSymbol::FULLSQUARE ;
                    break ;
                case SPAIopPMI_STAR:
                    result = PMIArrowSymbol::STAR ;
                    break ;
                case SPAIopPMI_DOT:
                    result = PMIArrowSymbol::DOT ;
                    break ;
                case SPAIopPMI_SMALLDOT:
                    result = PMIArrowSymbol::SMALLDOT ;
                    break ;
                case SPAIopPMI_MISC1:
                    result = PMIArrowSymbol::MISC1 ;
                    break ;
                case SPAIopPMI_MISC2:
                    result = PMIArrowSymbol::MISC2 ;
                    break ;
                case SPAIopPMI_FULLCIRCLE2:
                    result = PMIArrowSymbol::FULLCIRCLE2 ;
                    break ;
                case SPAIopPMI_FULLSQUARE2:
                    result = PMIArrowSymbol::FULLSQUARE2 ;
                    break ;
                case SPAIopPMI_OPEN_ARROW:
                    result = PMIArrowSymbol::OPEN_ARROW ;
                    break ;
                case SPAIopPMI_UNFILLED_ARROW:
                    result = PMIArrowSymbol::UNFILLED_ARROW ;
                    break ;
                case SPAIopPMI_BLANKED_ARROW:
                    result = PMIArrowSymbol::BLANKED_ARROW ;
                    break ;
                case SPAIopPMI_FILLED_ARROW:
                    result = PMIArrowSymbol::FILLED_ARROW ;
                    break ;
                case SPAIopPMI_UNFILLED_CIRCLE:
                    result = PMIArrowSymbol::UNFILLED_CIRCLE ;
                    break ;
                case SPAIopPMI_BLANKED_CIRCLE:
                    result = PMIArrowSymbol::BLANKED_CIRCLE ;
                    break ;
                case SPAIopPMI_FILLED_CIRCLE:
                    result = PMIArrowSymbol::FILLED_CIRCLE ;
                    break ;
                case SPAIopPMI_CROSSED_CIRCLE:
                    result = PMIArrowSymbol::CROSSED_CIRCLE ;
                    break ;
                case SPAIopPMI_BLANKED_SQUARE:
                    result = PMIArrowSymbol::BLANKED_SQUARE ;
                    break ;
                case SPAIopPMI_FILLED_SQUARE:
                    result = PMIArrowSymbol::FILLED_SQUARE ;
                    break ;
                case SPAIopPMI_BLANKED_TRIANGLE:
                    result = PMIArrowSymbol::BLANKED_TRIANGLE ;
                    break ;
                case SPAIopPMI_FILLED_TRIANGLE:
                    result = PMIArrowSymbol::FILLED_TRIANGLE ;
                    break ;
                case SPAIopPMI_MANIPULATOR_SQUARE:
                    result = PMIArrowSymbol::MANIPULATOR_SQUARE ;
                    break ;
                case SPAIopPMI_MANIPULATOR_DIAMOND:
                    result = PMIArrowSymbol::MANIPULATOR_DIAMOND ;
                    break ;
                case SPAIopPMI_MANIPULATOR_CIRCLE:
                    result = PMIArrowSymbol::MANIPULATOR_CIRCLE ;
                    break ;
                case SPAIopPMI_MANIPULATOR_TRIANGLE:
                    result = PMIArrowSymbol::MANIPULATOR_TRIANGLE ;
                    break ;
                case SPAIopPMI_DOUBLE_OPEN_ARROW:
                    result = PMIArrowSymbol::DOUBLE_OPEN_ARROW ;
                    break ;
                case SPAIopPMI_WAVE:
                    result = PMIArrowSymbol::WAVE ;
                    break ;
                default:
                    break;
            }

            return result ;
        }
        
        PMICalloutFeatureAnnotationType ToCalloutFeatureAnnotationType(const SPAIopPMICalloutFeatureAnnotationType & annotationType) 
        {
            PMICalloutFeatureAnnotationType result = PMICalloutFeatureAnnotationType::FEATURETYPE_UNKNOWN ;
            switch (annotationType) {
                case SPAIopPMI_FEATURETYPE_UNKNOWN:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_UNKNOWN ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLE_UNKNOWN:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLE_UNKNOWN ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTFIT:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTFIT ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTDEPTH:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTDEPTH ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTDIAMETER:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTDIAMETER ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTSCREWSIZE:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTSCREWSIZE ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTCOUNTERBOREDEPTH:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTCOUNTERBOREDEPTH ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTCOUNTERBOREDIAMETER:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTCOUNTERBOREDIAMETER ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTPATTERNCOUNT:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTPATTERNCOUNT ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTPITCH:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTPITCH ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTANGLE:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTANGLE ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTPATTAPERANGLE:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTPATTAPERANGLE ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTCOUNTERSINKDIAMETER:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTCOUNTERSINKDIAMETER ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTPATCOUNTERSINKANGLE:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTPATCOUNTERSINKANGLE ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTTHREADDEPTH:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTHREADDEPTH ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTTHREADSIZE:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTHREADSIZE ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTTHREADMINORDIA:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTHREADMINORDIA ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTTHREADMAJORDIA:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTHREADMAJORDIA ;
                    break ;
                case SPAIopPMI_FEATURETYPE_HOLECALLOUTTAPDRILLDIA:
                    result = PMICalloutFeatureAnnotationType::FEATURETYPE_HOLECALLOUTTAPDRILLDIA ;
                    break ;
                default:
                    break;
            }
            return result ;
        }
    }

}

AMCAX_EXCHANGE_NAMESPACE_END